﻿/** ---------- AULAC SOFT ------------- **/
/* ----- Author Write: H.Rin ----- */
/* ----- Create Date: 01/05/2011 ----- */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Aulac.Global.Xml;
using Aulac.Rsc.Ems.Tags;
using Aulac.Global.Common;
using Aulac.Rsc.Ems;
using Aulac.Srv.Db.Common;
using Aulac.Global.Exceptions;
using Aulac.Srv.Db.Data.Ems.InvJrns;
using Aulac.Rsc;
using Aulac.ErrCodes;

namespace Aulac.Srv.Db.Data.Ems.Stores.RelsStores
{
    partial class VchRelsStoreMng
    {        
        #region Private
        private bool AddVchStoreHeader(XmlElement eVch, ref string pRelsVchPrkID, ref string pVchType)
        {
            /* Author Write: H.Rin */
            /* Code Update: 01/05/2010 */

            XmlElement eHeader = XmlProcess.GetVchHeaderElm(eVch);
            
            pRelsVchPrkID = XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchRelsInvPrkID);
            pVchType = XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchTypeID);

            string sVchNo = XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchNo);
            if (Aulac.Global.Common.ValueHelper.isEmpty(sVchNo) || IsExistVchNo(pVchType, sVchNo))
            {
                string sVchName = "";
                sVchNo = GetNewVchNoDb(pVchType, ref sVchName);
                if (ValueHelper.isEmpty(sVchName))
                    sVchName = XmlProcess.GetValueVchHeader(eHeader, tagVch.Inv.VchName);
                XmlProcess.SetAtrb(ref eHeader, tagVch.Inv.VchNo, sVchNo);
                XmlProcess.SetAtrb(ref eHeader, tagVch.Inv.VchName, sVchName);
            }

            string[] arr = VchRelsStoreInfo.mListRelsVchH.GetRange(1, VchRelsStoreInfo.mListRelsVchH.Count - 1).ToArray();
            sqlQuery = SqlHelper.CreateSqlInsert(VchRelsStoreInfo.VchRelsInvHeader, arr);

            DbDataProvider.AddParamToCmd(mDbCmd, eHeader, arr);
            if (DbDataProvider.ExecuteNonQuery(ref mDbCmd, sqlQuery) <= 0)
                return false;

            pRelsVchPrkID = DbDataProvider.SelectMaxID(mDbCmd, VchRelsStoreInfo.VchRelsInvHeader, tagVch.Inv.VchRelsInvPrkID);
            XmlProcess.SetAtrb(ref eHeader, tagVch.Inv.VchRelsInvPrkID, pRelsVchPrkID);
            return true;
        }

        private bool IsExistVchNo(string pVchType, string pVchNo)
        {
            /* Author Write: H.Rin */
            /* Code Update: 01/05/2010 */

            sqlQuery = string.Format("SELECT TOP 1 {0} FROM {1}", tagVch.Inv.VchNo, VchRelsStoreInfo.VchRelsInvHeader);
            sqlQuery += string.Format(" WHERE ({0} = ?) AND ({1} = ?)AND ({2} BETWEEN ? AND ?)", tagVch.Inv.VchTypeID, tagVch.Inv.VchNo, tagVch.Inv.VchDate);
            return !ValueHelper.isEmpty(DbDataProvider.ExecuteScalar(mDbCmd, sqlQuery, pVchType, pVchNo, DateBeginFnc, DateEndFnc));
        }

        private bool AddVListStoreLine(XmlNodeList xmlNodeList, string sVchID)
        {
            /* Author Write: H.Rin */
            /* Code Update: 01/05/2010 */

            if (null == xmlNodeList)
                throw new AulacException(this, "AddVListStoreLine", "No Load data document!");
            try
            {
                sqlQuery = SqlHelper.CreateSqlInsert(VchRelsStoreInfo.VchRelsInvLine, VchRelsStoreInfo.mListRelsVchL.ToArray());

                for (int i = 0; i < xmlNodeList.Count; i++)
                {
                    XmlElement eLine = xmlNodeList[i] as XmlElement;
                    XmlProcess.SetAtrb(ref eLine, tagVch.Inv.VchRelsInvPrkID, sVchID);
                    XmlProcess.SetAtrb(ref eLine, tagVch.Inv.ItemLine, (i + 1));

                    DbDataProvider.AddParamToCmd(mDbCmd, eLine, VchRelsStoreInfo.mListRelsVchL.ToArray());
                    DbDataProvider.ExecuteNonQuery(ref mDbCmd, sqlQuery);
                }
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private bool UpdateInvJournal(XmlDataDocument xmlDoc, out XmlDataDocument xmlQtyLost)
        {
            XmlDataDocument xmlInvStore = CreateXmlInvJournal(xmlDoc);

            InvJrnMng InvJrn = new InvJrnMng(this.DbDataProvider.DbAulacConnection);
            return InvJrn.SetInvJrn(xmlInvStore, out xmlQtyLost);
        }

        private XmlDataDocument CreateXmlInvJournal(XmlDataDocument xmlStore)
        {
            XmlDataDocument xmlDoc = CreateXmlDocument("", "");
            XmlElement eHeader = XmlProcess.GetVchHeaderElm(xmlStore);
            XmlElement eInvJrn = XmlInvJrnHelper.AddInvJrnElm(xmlDoc);
            XmlElement eInvHeader = XmlInvJrnHelper.AddInvJrnHeader(eInvJrn);

            TagStores sTagStore = (TagStores)ValueHelper.ChangeType(XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.TagStore), typeof(TagStores));
            string sStorePrkID = XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.StorePrkID);
            XmlProcess.SetAtrb(ref eInvHeader, tagVch.Inv.InvJrnPrkID, "");
            XmlProcess.SetAtrb(ref eInvHeader, tagVch.Inv.VchOrgID, XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchRelsInvPrkID));
            XmlProcess.SetAtrb(ref eInvHeader, tagVch.Inv.VchOrgTypeID, XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchTypeID));
            XmlProcess.SetAtrb(ref eInvHeader, tagVch.Inv.VchDate, XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchDate));
            XmlProcess.SetAtrb(ref eInvHeader, tagVch.Inv.VchNo, XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchNo));
            XmlProcess.SetAtrb(ref eInvHeader, tagVch.Inv.Note, XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.Note));
            XmlProcess.SetAtrb(ref eInvHeader, tagVch.Inv.VchName, XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchName));
            XmlProcess.SetAtrb(ref eInvHeader, tagVch.Inv.IsCheckQtyLost, XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.IsCheckQtyLost));

            XmlNodeList listLine = XmlProcess.GetListVchLineItem(xmlStore);

            IEnumerable<XmlElement> l = listLine.Cast<XmlElement>();
            var result = from s in l.AsEnumerable()
                         group s by new
                         {
                             StorePrkID = XmlProcess.GetValueAtrb(s, tagVch.Inv.StorePrkID),
                             ItemPrkID = XmlProcess.GetValueAtrb(s, tagVch.Inv.ItemPrkID)
                         } into grpData
                         select new
                         {
                             grpData.Key,
                             Quantity = grpData.Sum(s => XmlProcess.GetValueDoubleAtrb(s, tagVch.Inv.Quantity)),
                             PrimeCostInExc = grpData.Sum(s => XmlProcess.GetValueDoubleAtrb(s, tagVch.Inv.Quantity) * XmlProcess.GetValueDoubleAtrb(s, tagVch.Inv.PrimeCostInExc)) / grpData.Sum(s => XmlProcess.GetValueDoubleAtrb(s, tagVch.Inv.Quantity))
                         };
            int lIndex = 0;
            foreach (var e in result)
            {
                XmlElement eLine = XmlInvJrnHelper.AddInvJrnItemOfInvJrn(eInvJrn);
                double dQty = e.Quantity;
                if (sTagStore == TagStores.OutputStore)
                    dQty = -dQty;
                XmlProcess.SetAtrb(ref eLine, tagVch.Inv.ItemLine, ++lIndex);
                string lStorePrkID = e.Key.StorePrkID;

                XmlProcess.SetAtrb(ref eLine, tagVch.Inv.StorePrkID, e.Key.StorePrkID);
                XmlProcess.SetAtrb(ref eLine, tagVch.Inv.ItemPrkID, e.Key.ItemPrkID);
                XmlProcess.SetAtrb(ref eLine, tagVch.Inv.Quantity, dQty);
                XmlProcess.SetAtrb(ref eLine, tagVch.Inv.PrimeCostInExc, e.PrimeCostInExc);
                XmlProcess.SetAtrb(ref eLine, tagVch.Inv.QtyOnhand, 0);
                XmlProcess.SetAtrb(ref eLine, tagVch.Inv.AmtOnhandInExc, 0);
            }
            return xmlDoc;
        }

        private bool UpdateVchStoreHeader(XmlElement eVch, ref string pVchID, ref string pVchType)
        {
            XmlElement eHeader = XmlProcess.GetVchHeaderElm(eVch);
            pVchID = XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchRelsInvPrkID);
            string sVchDate = XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchDate);
            pVchType = XmlProcess.GetValueAtrb(eHeader, tagVch.Inv.VchTypeID);

            string[] arr = VchRelsStoreInfo.mListRelsVchH.GetRange(1, VchRelsStoreInfo.mListRelsVchH.Count - 1).ToArray();
            sqlQuery = SqlHelper.CreateSqlUpdate(VchRelsStoreInfo.VchRelsInvHeader, arr);
            sqlQuery += string.Format(" WHERE {0} = ?", tagVch.Inv.VchRelsInvPrkID);
            DbDataProvider.AddParamToCmd(mDbCmd, eHeader, arr);
            DbDataProvider.AddParamToCmd(mDbCmd, false, pVchID);

            return DbDataProvider.ExecuteNonQuery(ref mDbCmd, sqlQuery) > 0;
        }

        private bool DelVchStoreHeaderDb(string pStoreMdnVPrkID)
        {
            /* Code date: 12/17/2010 by Thangnc*/

            sqlQuery = SqlHelper.CreateSqlDelete(VchRelsStoreInfo.VchRelsInvHeader, tagVch.Inv.VchRelsInvPrkID);
            return DbDataProvider.ExecuteNonQuery(ref mDbCmd, sqlQuery, pStoreMdnVPrkID) >= 0;
        }

        private bool DelVchStoreLineDb(string pVchID)
        {
            sqlQuery = SqlHelper.CreateSqlDelete(VchRelsStoreInfo.VchRelsInvLine, tagVch.Inv.VchRelsInvPrkID);
            return DbDataProvider.ExecuteNonQuery(ref mDbCmd, sqlQuery, pVchID) >= 0;
        }

        private bool DelVchStoreDb(string pVchRelsPrkID, string pVchTypeID, bool pIsCheckLostQty)
        {
            DelVchStoreLineDb(pVchRelsPrkID);
            DelVchStoreHeaderDb(pVchRelsPrkID);
            XmlDataDocument xmlQtyLost = null;
            if (!DelInvJournal(pVchRelsPrkID, pVchTypeID, pIsCheckLostQty, out xmlQtyLost) && xmlQtyLost != null)
                throw new AulacException(ErrorCode.Error0010, xmlQtyLost.OuterXml, "");

            return true;
        }

        private bool DelInvJournal(string pVchOrgID, string pVchTypeID, bool pIsCheckLostQty, out XmlDataDocument xmlQtyLost)
        {
            InvJrnMng InvJrn = new InvJrnMng(DbDataProvider.DbAulacConnection);
            string sInvJrnPrkID = InvJrn.GetInvJrnPrkID(pVchOrgID, pVchTypeID);
            return InvJrn.DelIvnJrn(sInvJrnPrkID, pIsCheckLostQty, out xmlQtyLost);
        }

        private XmlDataDocument GetVchStoreDb(string sVoucherID)
        {
            string str = StringHelper.ConvertArrayToString(", h.", VchRelsStoreInfo.mListRelsVchH.ToArray());
            str = "h." + str;
            string str1 = StringHelper.ConvertArrayToString(", l.", VchRelsStoreInfo.mListRelsVchL.GetRange(1, VchRelsStoreInfo.mListRelsVchL.Count - 1).ToArray());
            str1 = "l." + str1;
            string str3 = string.Format(" m.{0}, m.{1}, m.{2},m.{3}", tagVch.Inv.ItemName, tagVch.Inv.Unit, tagVch.Inv.ItemID, tagItems.Item.ItemGrpID);
            sqlQuery = string.Format("SELECT {0}, {1}, {2} FROM {3} h INNER JOIN {4} l", str, str1, str3, VchRelsStoreInfo.VchRelsInvHeader, VchRelsStoreInfo.VchRelsInvLine);
            sqlQuery += string.Format(" ON h.{0} = l.{1}", tagVch.Inv.VchRelsInvPrkID, tagVch.Inv.VchRelsInvPrkID);
            sqlQuery += string.Format(" INNER JOIN {0} m ON l.{1}  = m.{2}", TableNames.Dm_MdnItems, tagVch.Inv.ItemPrkID, tagVch.Inv.ItemPrkID);
            sqlQuery += string.Format(" WHERE (h.{0} = ?)", tagVch.Inv.VchRelsInvPrkID);

            DbDataReader = DbDataProvider.ExecuteReader(mDbCmd, sqlQuery, sVoucherID);
            XmlDataDocument xmlDoc = CreateXmlDocument("", "");
            XmlElement eHeader = null;
            XmlElement eVoucher = XmlProcess.AddVchElm(ref xmlDoc);
            while (DbDataReader.Read())
            {
                if (eHeader == null)
                {
                    eHeader = XmlProcess.AddVchHeaderElm(ref eVoucher);
                    DbDataProvider.GetValuesToXml(DbDataReader, ref eHeader, VchRelsStoreInfo.mListRelsVchH.ToArray());
                }
                XmlElement eLine = XmlProcess.AddVchLineItemElm(eVoucher);
                DbDataProvider.GetValuesToXml(DbDataReader, ref eLine, VchRelsStoreInfo.mListRelsVchL.ToArray());
                DbDataProvider.GetValuesToXml(DbDataReader, ref eLine, tagVch.Inv.ItemName, tagVch.Inv.Unit, tagVch.Inv.ItemID, tagItems.Item.ItemGrpID);
            }
            DbDataReader.Close();
            return xmlDoc;
        }

        private XmlDataDocument CreateXmlAcntJrn(string pVchRelsInvPrkID)
        {
            throw new NotImplementedException();
        }

        private string GetNewVchNoDb(string sVchTypeID, ref string sVchName)
        {
            /* Author Write: H.Rin */
            /* Code Update: 01/05/2010 */

            return GetNewVchNo(VchRelsStoreInfo.VchRelsInvHeader, tagVch.Inv.VchRelsInvPrkID, sVchTypeID, ref sVchName);
        }
        #endregion
    }
}
